<?

class ObjectClass extends Root{
	var $Cibles = Array();
	var $Proprietes = Array();
	var $Functions = Array();
	var $Etrangeres = Array();
	var $parentOf = Array();
	var $childOf = Array();
	var $titre;
	var $driver;
	var $Module='';
	var $Prefix;
	var $Default=0;
	var $DroitsDefault;
	var $Description;
	var $Reference = 0;
	var $Heritage = 0;
	var $Dico = 0;
	var $Class = 0;
	var $Conf;
	var $Icon;
	var $objRef;
	var $References ="";
	var $ReferChilds;
	var $ProprietesRef;
	var $isLongKey = Array("1,n","0,n");
	var $isShortKey = Array("1,1","0,1");
	/*var $NeededPHP = Array("Id"=> "integer", "tmsCreate"=> "string",
			      "userCreate"=> "string","tmsEdit"=> "string",
	 		      "userEdit"=>"string","uid"=>"integer","gid"=>"integer","gmod"=>"integer","umod"=>"integer","omod"=>"integer");*/
	var $master;
	var $ObjectTable = Array();
	var $Bdd = 0;								//BASE DE DONNEE PAR DEFAUT

	/* -----------------------------
	 |       Initialisation       |
	 -----------------------------*/

	function createInstance($schema=false,$Module){
		if (is_array($schema['@']))$Driver = $schema['@']['driver'].'Driver';
		else $Driver = $schema['driver'].'Driver';
		$Class = new $Driver($schema,$Module);
		$Class->Module = $Module;
		return $Class;
	}


	function __construct($schema=false,$Module) {
		$this->Module = $Module;
		$this->Prefix = MAIN_DB_PREFIX.$Module."-";
		if ($schema) $this->initFromXml($schema);
	}

	function initFromXml($schema){
		//Initialisation des attributs de l objectClass
		$this->titre = $schema['@']['title'];
		$this->driver = $schema['@']['driver'].'Driver';
		$this->DroitsDefault = $schema['@']['Droits'];
		$this->AccessPoint = $schema['@']['AccessPoint'];
		$this->Default = $schema['@']['Default'];
		$this->Dico = $schema['@']['Dico'];
		$this->Master = $schema['@']['master'];
		$this->Heritage = $schema['@']['Heritage'];
		$this->Class = $schema['@']['Class'];
		$this->Description = $schema['@']['Description'];
		if ($schema['@']['Bdd'])$this->Bdd = $schema['@']['Bdd'];
		$this->Reference = $schema['@']['Reference'];
		$this->Icon = $schema['@']['Icon'];
		$this->generateUrl = $schema['@']['generateUrl'];
		$this->Display = $schema['@']['Display'];
		if ($schema['@']['driver']=="ldap"){
			$this->ObjectClass = $schema['@']['ObjectClass'];
		}
		
		//INTIALISATION DES PROPRIETES
		$temp = $schema['#']['PROPERTIES'];
		$if = $schema["#"]['IF'];
		$moreProps = array();
		if (is_array($if)) foreach ($if as $i)
		{
		  $moreProps=array_merge($moreProps,$i['#']['PROPERTIES']);
		}
		$temp = array_merge($temp,$moreProps);
		for ($i=0;$i<sizeof($temp);$i++) {
			$this->Proprietes[$temp[$i]['#']] = $this->parseAttributes($temp[$i]['@'],$temp[$i]['#']);
			$this->Proprietes[$temp[$i]['#']]["Emp"] = $i;
		}
		//INITILISATION DES PROPRIETES DYNAMIQUES
		if ($this->generateUrl){
			//On ajoute une proprietes Url
			$this->Proprietes["Url"] = $this->parseAttributes(array("type"=>"link","searchOrder"=>3,"auto"=>1),"Url");
		}

                //GESTION DES IF
                $temp = $schema['#']['IF'];
                for( $i=0; $i<sizeof($temp); $i++ ) {
			//On ajoute les props
			$temp2 = $temp[$i]['#']['PROPERTIES'];
			$ps = array();
			for ($j=0;$j<count($temp2);$j++) {
			//$this->Proprietes[$temp2[$j]['#']] = $this->parseAttributes($temp2[$j]['@'],$temp2[$j]['#']);
			//$this->Proprietes[$temp2[$j]['#']]["Emp"] = $nbprop + $j;
			$ps[] = $temp2[$j]['#'];
			}
			$this->Conditions[] = array("Name" => $temp[$i]['@']['name'],
						"Value" => explode(",",$temp[$i]['@']['value'] ),
						"About" => $temp[$i]['@']['about'],
						"PropsName" => $ps);
                }
		//INITIALISATION DES ASSOCIATIONS
		$temp = $schema['#']['FKEY'];
		for ($i=0;$i<count($temp);$i++) {
			$this->Etrangeres[$temp[$i]['#']] = $this->parseAttributes($temp[$i]['@']);
			//On affiche aussi le champ Objet, cad le nom de lObj proche
			$Name = explode(",",$this->Etrangeres[$temp[$i]['#']]['data']);
			$this->Etrangeres[$temp[$i]['#']]['Objet'] = $Name[0];
			$this->Etrangeres[$temp[$i]['#']]['Target'] = $Name[1];
			if (!isset($this->Etrangeres[$temp[$i]['#']]["default"]))
			$this->Etrangeres[$temp[$i]['#']]["default"] = 1;
		}
		//INITIALISATION DES REFERENCES
		$temp = $schema['#']['REFERENCE'];
		for ($i=0;$i<count($temp);$i++) {
			$this->Etrangeres[$temp[$i]['#']] = $this->parseAttributes($temp[$i]['@']);
			// 			On affiche aussi le champ Objet, cad le nom de l'Obj proche
			$Name = explode(",",$this->Etrangeres[$temp[$i]['#']]['data']);
			$this->Etrangeres[$temp[$i]['#']]['Objet'] = $this->titre;
			$this->Etrangeres[$temp[$i]['#']]['Target'] = $this->Etrangeres[$temp[$i]['#']]['target'];
			$this->Etrangeres[$temp[$i]['#']]['Reference'] = 1;
			$this->Etrangeres[$temp[$i]['#']]['Module'] = $this->Etrangeres[$temp[$i]['#']]['module'];
		}
		//INITIALISATION DES FONCTIONS
		$temp = $schema['#']['FUNCTION'];
		for ($i=0;$i<count($temp);$i++) {
			$this->Functions[$temp[$i]['#']] = $this->parseAttributes($temp[$i]['@']);
		}
                
		//INITIALISATION DU PILOTE

		$this->createTargets();

		//GESTION DES TYPES
// 		$InvProp = array_keys($this->Proprietes);
// 		for ($i=0;$i<count($this->Proprietes);$i++){
// 			$this->Proprietes[$InvProp[$i]] =  $this->initSpecialTypes($this->Proprietes[$InvProp[$i]]);
// 		}

	}

	function initFromReference($Tab,$Nom){
		//Initialisation des attributs de l objectClass
		$this->titre = $Nom;
		$this->driver = $Tab['driver'].'Driver';
		$this->AccessPoint = 0;
		$this->Master = 0;
		$this->Heritage = 0;
		$this->Description = $Tab['description'];
		$this->Icon = $Tab['Icon'];

		//INTIALISATION DES PROPRIETES
		$this->Proprietes['Reference'.$Tab["Module"]] = $Tab;
		$this->Proprietes['Reference'.$Tab["Module"]]['type']= 'ObjectClass';
		$this->Proprietes['Reference'.$Tab["Module"]]['length']= '255';
		$this->Proprietes['Reference'.$Tab["Module"]]['titre']= 'Reference'.$Tab["Module"];
		$this->Proprietes['Reference'.$Tab["Module"]]['special']= 'Reference';
		$this->Proprietes['Reference'.$Tab["Module"]]['searchOrder']= 1;
		//INITIALISATION DES ASSOCIATIONS
		$t=explode(",",$Tab["data"]);
		$this->Etrangeres[$this->titre]['card']= '1,1';
		$this->Etrangeres[$this->titre]['data']= $Tab["data"];
		$this->Etrangeres[$this->titre]['Target']= $t[1];
		$this->Etrangeres[$this->titre]['Table']= $t[0];
		$this->Etrangeres[$this->titre]['Champ']= $t[1];
		$this->Etrangeres[$this->titre]['behaviour']= "Integrated";
		//INITIALISATION DU PILOTE
		$this->createTargets();

		//GESTION DES TYPES
/*		$InvProp = array_keys($this->Proprietes);
		for ($i=0;$i<count($this->Proprietes);$i++){
			$this->Proprietes[$InvProp[$i]] =  $this->initSpecialTypes($this->Proprietes[$InvProp[$i]]);
		}*/
	}

	function checkNew($Drv="",$Data=""){
		if (empty($Drv)) $Drv = $this->Conf["CHECKFROM"];
		$Drv = $Drv."Driver";
		return $this->checkNew($Data);
	}

	function parseAttributes($tab,$Nom='') {
		//ParseAttributes permet de transformer le schema en attributs de la classe
		//On recherche les attributs...
		$v=0;
		$nbAttr = count($tab);
		$tabTemp = array_keys($tab);
		//Et ensuite on fait un switch qui les charge dans le tableau
		for ($i=0;$i<$nbAttr;$i++) {
			if($tab['card']!='0,n' || $tab['card']!='1,n') {
				switch ($tabTemp[$i]) {
					case 'values':	//Valeurs possible
						$temp = explode(",",$tab[$tabTemp[$i]]);
						foreach ($temp as $t) {
							$Result["Values"][] = $t;
						}
						break;
					case 'type':		//Type l information
					case 'query':		//Execution requete
					case 'default':		//Valeurs par defaut
					case 'color':		//Type de couleur en hexadecimal
					case 'param':		//Parametre quand type = ObjectClass
					case 'card':		//FKEY : Cardinalite
					case 'data':		//FKEY : Nom de la liaison
					case 'description':	//Description
					case 'length':		//Longueur
					case 'null':		//definie la possibilite d'une valeur nulle
					case 'searchOrder':	//Ordre de recherche
					case 'inherit':		//Definie un heritage
					case 'behaviour':	//Definie un comportement
					case 'action':		//Definie un comportement
					case 'obligatoire':	//Champ obligatoire
					case 'unique':		//Valeur unique
					case 'target':		//Dictionnaire automatique ??
						$Result[$tabTemp[$i]]=$tab[$tabTemp[$i]];
					break;
					default:
						$Process = new Process();
						$Result[$tabTemp[$i]]=$Process->processingVars($tab[$tabTemp[$i]]);
						break;
				}
			}
		}
		return $Result;
	}

	function saveGroupData($gId){
		return $this->saveGroupData($gId);
	}

	function isProperties($Property) {
		//Verifie si Property est une propriete
		if (array_key_exists($Property,$this->Proprietes)) return true;
		if (array_key_exists($Property,ObjectConst::NeededPHP())) return true;
		return false;
	}


	function isFKey($Fkey) {
		//Verifie si Fkey est une clef etrangere
		$Test = in_array($this->Etrangeres[$Fkey]['card'],$this->isShortKey);
		return (array_key_exists($Fkey,$this->Etrangeres) && $Test) ? true:false;
	}

	function isChildOf($Obj){
		if (sizeof($this->childOf))foreach ($this->childOf as $Link) {
			if ($Link["Titre"]==$Obj) return true;
		}
		return false;
	}

	/* -----------------------------------------------------------------
	 |       Verification et modification des donnees structure       |
	 -----------------------------------------------------------------*/

	function countDb(){
		return $this->countDb();
	}


	function idPossess($id){
		//Dummy qui permet de verifier si l'user a bien l'id specifie
		return $this->idPossess($id);
	}

	function Verify(){
		return mysqlCheck::Verify();
	}


	function Check() {
		//Verifie et modifie les donnes qui differe entre l'objet et la table SQL
		if (!$this->Verify()) $GLOBALS["Systeme"]->Error->sendErrorMsg(60,1);
		$this->initData();
	}
	function getCard($Class) {
		if (is_array($this->childOf))foreach ($this->childOf as $Co) {
			if ($Co["Titre"]==$Class) return $Co["Card"];
		}
	}

	function getSchema(){
		//Renvoie le schema dans un tableau
		return Array('Properties'=>$this->Proprietes, 'FKeys'=>$this->Etrangeres);
	}


	function findReflexive(){
		//On recherche la clef de parente
		foreach ($this->Etrangeres as $Key=>$Etr){
			$Out=explode(",",$Etr['data']);
			if ($Out[0]==$this->titre) return $Key;
		}
		return false;
	}

	function findReflexiveCard(){
		//On recherche la clef de parente
		foreach ($this->childOf as $Key){
			if ($Key["Titre"]==$this->titre) return $Key["Card"];
		}
		return false;
	}
	function createTargets() {
		//Creer le tableau des cibles (priorite de recherches)
		$this->Cibles['Id'] = 0;
		// On gï¿œï¿œe un tableau avec la propriete et son indice de priorite.
		foreach ($this->Proprietes as $Clef=>$Propriete){
			if ($Propriete['searchOrder'] != NULL) {
				$this->Cibles[$Clef]= $Propriete['searchOrder'];
			}
		}
		//On range le tableau selon ses clefs
		asort($this->Cibles);
		return true;
	}


	function getPropType($Nom){
		//Renvoie le type d-une propriete
		if (array_key_exists($Nom,$this->Proprietes)) $Type = $this->Proprietes[$Nom]["type"];
		if (array_key_exists($Nom,$this->Etrangeres)) $Type = "integer";
		$Needed = ObjectConst::NeededPHP();
		if (array_key_exists($Nom,$Needed)) $Type =$Needed[$Nom];
		switch (strtolower($Type)){
			case "autodico":
			case "int":
				$Type="integer";
				break;
			case "private":
			case "image":
			case "url":
			case "txt":
			case "text":
			case "titre":
			case "canonic":
			case "varchar":
			case "link":
				$Type="string";
				break;
			case "boolean":
				break;
		}
		return ($Type) ? $Type:false;
	}

	function getSpecialProp($Name){
		//Renvoie les proprietes d un certain type
		$Tab = $this->Proprietes;
		foreach ($Tab as $Nom=>$Value) {
			if ($Value["special"]==$Name||$Value["type"]==$Name) {
				$Result[$Nom] = $Value;
			}
		}
		return (is_array($Result)) ? $Result:false;
	}

	/* -------------------------------------
	 |       Fonctions de recherche       |
	 -----------------------------------  */

	function findKey($DataName,$Type='child',$Option=''){
		//Renvoie le nom du champ tendant vers $DataName dans la table courante.
		//On verifie si on a le nom d'un objectclass, si oui on renvoie le nom de champ
		if ($Type=="child") $Tab = $this->parentOf;
		if ($Type=="parent") $Tab = $this->childOf;
		if (is_array($Tab)) foreach ($Tab as $Etrangere){
			if ($Etrangere["Titre"]==$DataName && $Etrangere["Default"]==1) {
				if ($Option=="Card") return $Etrangere['Card'];
				else return $Etrangere['FKey'];
			}
		}
		//On verifie si on a le nom d'un champ. Si il s'agit d'une double fkey, par exemple.
		if (is_array($Tab)) foreach ($Tab as $Etrangere){
			if ($Etrangere["FKey"]==$DataName)
			{
				if ($Option=="Card") return $Etrangere['Card'];
				else return $Etrangere['FKey'];
			}
		}
		return false;
	}

	function isReflexive($P=""){
		if (!empty($P))
		{
			$T = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->findByTitle($P);
			$Object = $GLOBALS["Systeme"]->Modules[$this->Module]->Db->ObjectClass[$T];
		}else{$Object = $this;}
		if (is_array($Object->childOf)&&sizeof($Object->childOf)) foreach($Object->childOf as $Enfant){
			if ($Object->titre==$Enfant["Titre"]) {
				if ($Enfant["Card"]=="0,1"||$Enfant["Card"]=="1,1"){
					return true;
				}else{
					return 2;
				}
			}
		}
		return false;
	}

	function getKey($Table,$Champ,$Type="child"){
		$Name = "Titre";
		if ($Type=="child") {$Tab = $this->parentOf;}
		if ($Type=="parent") $Tab = $this->childOf;
		if (is_array($Tab)&&sizeof($Tab)) foreach($Tab as $E){
			if ($E["FKey"]==$Champ && $E[$Name]==$Table) return $E;
		}
		return false;
	}

	function getKeyInfo($DataSource,$Value,$parent=false){
		//Construction du tableau d analyse
		$Ke = $this->findKey($DataSource,"child");
		$K = $this->getKey($DataSource,$Ke,"child");
		$TabAnalyse["Recherche"] = $Value;
		$TabAnalyse[($parent)?"Parent":"Nom"] = $this->titre;
		$TabAnalyse["Card"] = $K["Card"];
		$TabAnalyse["Champ"] = $K["Champ"];
		$TabAnalyse["Driver"] = $this->driver;
		$TabAnalyse["Table"] = $K["Table"];
		$TabAnalyse["Target"] = $K["Target"];
		$TabAnalyse["NomEnfant"] = $K["Titre"];
		$TabAnalyse["Out"] =($parent)?1:0;
		if ($this->isReflexive()) $TabAnalyse["Reflexive"] = true;
		return $TabAnalyse;
	}

	function Search($Key,$Value,$parent=false,$Select="",$GroupBy="") {
		$Result=false;
		if ($parent) {
			//RECHERCHE PARENT SIMPLE
			$Analyse[] = $Key;
			//Filtre
			$TabAnalyse["Recherche"] = $Value;
			$TabAnalyse["Nom"] =$Key["NomEnfant"];
			$TabAnalyse["Driver"] =$this->driver;
			$Analyse[] = $TabAnalyse;
			//Existe t il un filtre ?
			if (is_array($filtre)){
				$Analyse[] = array("Recherche"=>$filtre["Value"]);
			}
			//Analyse terminï¿œe donc on envoi maintenant la requete au pilote.
			$Results = $this->DriverSearch($Analyse,$Select,$GroupBy);
		}else{
			$TabAnalyse["Recherche"] = $Value;
			$TabAnalyse["Nom"] = $this->titre;
			$TabAnalyse["Driver"] = $this->driver;
			$TabAnalyse["Out"] = true;
			$TabAnalyse["Reflexive"] = $this->isReflexive();
			if (is_array($Key))$Analyse[] = $Key;
			$Analyse[] = $TabAnalyse;
			//Analyse terminï¿œe donc on envoi maintenant la requete au pilote.
			$Results = $this->DriverSearch($Analyse,$Select,$GroupBy);
// 			print_r($Results);
		}
		if (AUTO_COMPLETE_LANG&&$GLOBALS["Systeme"]->LangageDefaut!=$GLOBALS["Systeme"]->DefaultLanguage&&!$GLOBALS["Systeme"]->User->Admin){
			foreach ($GLOBALS["Systeme"]->Conf->get("GENERAL::LANGUAGE") as $Cod=>$Lang) {
				if ($Lang["DEFAULT"]) $DefautPref = $Cod;
			}
			if (is_array($Result)) for( $i=0; $i<sizeof($Result);$i++){
				foreach ($this->Proprietes as $Key=>$Prop){
					//Priorites de langage
					$Special = $this->Proprietes[$Key]["special"];
					if ($Special=="multi"&&$Result[$i][$Key]==""){
						$Result[$i][$Key] = $Result[$i][$DefautPref."-".$Key];
						//print_r($Result[$i]);
					//	echo "CHANGEMENT $Key => ".$Result[$i][$DefautPref."-".$Key]."\r\n";
					}
				}
			}
		}
		return $Results;
	}


	/* -------------------------------------------
	 |       Fonctions de calcul de notes       |
	 -------------------------------------------  */


	function calcNote($valeurEnr,$Recherche,$valeurCible){
		//Cette fonction permet de calculer la note qui classera les resultats
		$totalCibles = sizeof($this->Cibles);
		$note = (10/$totalCibles)*($totalCibles-($valeurCible/$totalCibles));
		//On obtient, appart pour Id, des notes inferieures a 10, auquel on va retirer la pertinence du resultat
		if ($Recherche != $valeurEnr){
			//Au cas ou la recherche soit au debut, a la fin ou au milieu
			$note=$this->attribNote($note,'!^'.$Recherche.'!i',$valeurEnr,2,$Recherche);
			$note=$this->attribNote($note,'!'.$Recherche.'$!i',$valeurEnr,3,$Recherche);
			$note=$this->attribNote($note,'!'.$Recherche.'!i',$valeurEnr,5,$Recherche);
		}
		return $note;
	}


	function attribNote($note,$eReg,$Chaine,$Facteur,$Recherche){
		//Cette fonction fait les calculs d'amputations de points pour calcNote
		if (preg_match($eReg, $Chaine)){
			$note = $note - ($Facteur/count($this->Cibles));
			$note = $note*(strlen($Recherche)/strlen($Chaine));
		}
		return $note;
	}

	//-------------------------------------------//
	// FONCTIONS UTILITAIRES
	//-------------------------------------------//



	function genererCode(){
		$cars="az0erty2ui3op4qs_5df6gh7jk8lm9wxcvbn-";
		$wlong=strlen($cars);
		$wpas="";
		$taille=20;
		srand((double)microtime()*1000000);
		for($i=0;$i<$taille;$i++){
			$wpos=rand(0,$wlong-1);
			$wpas=$wpas.substr($cars,$wpos,1);
		}
		return $wpas;
	}

 	function autoLink($Field,$Obj,$Prefixe="") {
        //Analyse des searchOrder pour Detecter de la chaine a encoder
        if ($Prefixe!="")$Prefixe.="-";
        foreach ($this->Cibles as $K=>$C) {
            if ($C>0&&$K!="Url"&&!$Ok){
                if ($this->getPropType($K)=="string") {
                    $Prop=$K;
                    $Ok=true;
                }
            }
        }
        if ($Prefixe!=""){
            $chaine = "_".$Obj[$Prefixe.$Prop];
            if ($chaine == "_"){
                $chaine = "_".$Obj[$Prop];
            }
        }else $chaine = "_".$Obj[$Prefixe.$Prop];
        $chaine=utf8_decode($chaine);
        $chaine=stripslashes($chaine);
        $chaine = preg_replace('`\s+`', '-', trim($chaine));
        $chaine = str_replace("'", "-", $chaine);
        $chaine = str_replace("?", "", $chaine);
        $chaine = str_replace("!", "", $chaine);
        $chaine = str_replace(".", "", $chaine);
        $chaine = preg_replace('`[\,\ \(\)\+\'\/\:]`', '-', trim($chaine));
        $chaine=strtr($chaine,utf8_decode("ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ?"),"aaaaaaaaaaaaooooooooooooeeeeeeeecciiiiiiiiuuuuuuuuynn-");
        $chaine = preg_replace('`[-]+`', '-', trim($chaine));
        $chaine =  utf8_encode($chaine);
        //ON verifie qu il n existe pas deja une entité avec la meme url
        $Suffixe=($Obj["Id"]!="")?"&Id!=".$Obj["Id"]:"";
        $modif = false;
        $chainet = preg_replace('`[\/]`', '-', trim($chaine));
        $Result =  $GLOBALS["Systeme"]->Modules[$this->Module]->callData($this->titre."/".$Field."=".$chainet.$Suffixe,"","","","","","COUNT(*)");
        if ($Result[0]["COUNT(*)"]>0)while ($Result[0]["COUNT(*)"]>0){
            $int++;
            $Result =  $GLOBALS["Systeme"]->Modules[$this->Module]->callData($this->titre."/".$Field."=".$int.$chainet.$Suffixe,"","","","","","COUNT(*)");
            $modif = true;
            //             echo $this->titre."/".$Field."=$int".$chaine.$Suffixe." => ".$Result[0]["COUNT(*)"]."\r\n";
        }
        if ($modif)$chaine=$int.$chaine;
        return $chaine;
    }
	function autoCanon($Obj,$Prefixe="") {
		//Analyse des searchOrder pour Detecter de la chaine a encoder
		if ($Prefixe)$Prefixe.="-";
		foreach ($this->Cibles as $K=>$C) {
			if ($C>0&&$K!="Url"){
				if ($this->getPropType($K)=="string"&&!$t) {
					$Prop=$K;$t=1;
				}
			}
		}
		$chaine = $Obj[$Prefixe.$Prop];
		//ON verifie qu il n existe pas deja une entité avec la meme url
		$chaine=utf8_decode($chaine);
		$chaine=strtr($chaine,utf8_decode("ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ"),"aaaaaaaaaaaaooooooooooooeeeeeeeecciiiiiiiiuuuuuuuuynn");
		if (strlen($chaine)>3) $chaine = preg_replace("#(e|s|es|ent)$#","",$chaine);
		return utf8_encode($chaine);
	}
	function changeRights($Id,$Ui="",$Gi="",$Um="",$Om="",$Gm=""){
// 		return $this->changeRights($Id,$Ui,$Gi,$Um,$Om,$Gm);
	}
	/*----------------------------------
	 |     Fonctions d'insertion       |
	 ----------------------------------*/

	function AddNeededFields($Obj='',$type){
		//Rajoute les champs necessaires a une insertion
		$LesDroits= Array("uid","gid","umod","gmod","omod");
		$Tableau = Array();
		if ($type == "OBJECT") $Tableau['Id']=$Obj["Id"];
		//On met a jour les tms et User
		$TimeStamp = time();
		$CurrentUser = $GLOBALS['Systeme']->User->Id ;
		if ($Obj["Id"]==NULL){
			if ($type!="ASSOC") {
				$Tableau['uid'] = $CurrentUser;
				$Tableau['gid'] = $GLOBALS["Systeme"]->User->Groups[0]->Id;
			}
			$Tableau['tmsCreate']=$TimeStamp;
			$Tableau['userCreate']=$CurrentUser;
		}else{
			if ($type!="ASSOC") {
				$Tableau['uid'] = $Obj['uid'];
				$Tableau['gid'] = $Obj['gid'];
			}
			$Tableau['tmsCreate']=$Obj['tmsCreate'];
			$Tableau['userCreate']=$Obj['userCreate'];
		}
		for ($i=0;$i<count($LesDroits);$i++)
		{
			if (!empty($Obj[$LesDroits[$i]])) $Tableau[$LesDroits[$i]] = $Obj[$LesDroits[$i]];
		}
		$Tableau['tmsEdit'] = $TimeStamp;
		$Tableau['userEdit'] = $CurrentUser;
		return $Tableau;
	}


	function Insert($Object){
// 		echo "INSERT OBJECT<br/> \r\n";
// 		print_r($Object);
		//Insere/met a jour un objet et ses clefs etrangeres
		$Obj = get_object_vars($Object);
		$OrdreProp = $this->AddNeededFields($Obj,"OBJECT");
		$Error = false;
		//Traitement multilingue
		$Prefixes = array();
		$DefaultLanguage=$GLOBALS["Systeme"]->DefaultLanguage;
		foreach ($GLOBALS["Systeme"]->Language as $Lang=>$Pref){
			if ($DefaultLanguage!=$Lang){
				$Prefixes[] = $Pref;
			}
		}
		foreach($this->Proprietes as $Key=>$Prop){
			//Si le champ est obligatoire et que l'insertion est vide, erreur
		  if ($Prop["obligatoire"] && !($Prop['type']=="boolean" && $Obj[$Key]==0) && empty($Obj[$Key]))
			{
				$GLOBALS["Systeme"]->Error->sendUserMsg(15,$Key);
				/*				echo $this->titre." Obligatoire ".$Key;
				 print_r($Prop);*/
				$Error = true;
			}
			if ($Prop["unique"] && !empty($Obj[$Key])&&empty($Obj["Id"]))
			{
				$Result =  $GLOBALS["Systeme"]->Modules[$this->Module]->callData($this->titre."/".$Key."=".$Obj[$Key]);
				if ($Result && $Result[0]["Id"]!=$Obj["Id"]){
					$GLOBALS["Systeme"]->Error->sendUserMsg(16,$Key);
					$Error=true;
				}
			}
			if($Prop["special"]=="random" &&( $Obj["tmsEdit"]<(time()-(CONNECT_TIMEOUT*60)) || $Obj["tmsEdit"]==NULL|| $Obj["CodeVerif"]=="")){
				$OrdreProp[$Key] = $this->genererCode();
			}else{
				if (empty($Prop["Ref"])) $OrdreProp[$Key]=$Obj[$Key];
			}
			if ($Prop["content"]=="link") {
				$OrdreProp[$Key] = $this->autoLink($Key,$Obj);
				if ($Prop["special"]=="multi") {
					//Pr tous les langages, on verifie q la variable de la prop existe.
					foreach ($Prefixes as $Prefixe){
						$OrdreProp[$Prefixe."-".$Key] = $this->autoLink($Key,$Obj,$Prefixe);
					}
				}
			}
			if ($Prop["content"]=="canonic") {
				$OrdreProp[$Key] = $this->autoCanon($Obj);
				if ($Prop["special"]=="multi") {
					//Pr tous les langages, on verifie q la variable de la prop existe.
					foreach ($Prefixes as $Prefixe){
						$OrdreProp[$Prefixe."-".$Key] = $this->autoCanon($Obj,$Prefixe);
					}
				}
			}
			if ($Prop["special"]=="multi") {
				//Pr tous les langages, on verifie q la variable de la prop existe.
				foreach ($Prefixes as $Prefixe){
					if (array_key_exists($Prefixe."-".$Key,$Obj)&&$OrdreProp[$Prefixe."-".$Key]==""){
						$OrdreProp[$Prefixe."-".$Key] = $Obj[$Prefixe."-".$Key];
					}
				}
			}

		}
		if ($Error) return false;
		//On insere ensuite les proprietes dans une variable objet
		$Properties = $OrdreProp;
		//Verification des droits
		if ($Properties["Id"] == NULL)
		{
			if (!empty($this->DroitsDefault))
			{
				if (empty($Properties["Gmod"])) $Properties["Gmod"] = $this->DroitsDefault[1];
				if (empty($Properties["Umod"])) $Properties["Umod"] = $this->DroitsDefault[0];
				if (empty($Properties["Omod"])) $Properties["Omod"] = $this->DroitsDefault[2];
			}
			if (empty($Properties["Gmod"])) $Properties["Gmod"] = 7;
			if (empty($Properties["Umod"])) $Properties["Umod"] = 7;
			if (empty($Properties["Omod"])) $Properties["Omod"] = 7;
		}else{
			if (empty($Properties["Gmod"])&&empty($Properties["gmod"])) $Properties["Gmod"] = 7;
			if (empty($Properties["Umod"])&&empty($Properties["umod"])) $Properties["Umod"] = 7;
			if (empty($Properties["Omod"])&&empty($Properties["omod"])) $Properties["Omod"] = 7;
		}
		//Ajout des clefs "courtes"
		if (is_array($Obj['Parents']))foreach ($Obj['Parents'] as $leParent){
			if (is_array($leParent))if ($leParent["Action"] == 2  && in_array($this->findKey($leParent["Fkey"],'parent','Card'),$this->isShortKey)) {
				$NomChamp = $this->findKey($leParent['Fkey'],'parent');
				$Properties[$NomChamp] = $leParent["Id"];
			}
			if (is_object($leParent))if ($leParent->Action == 2  && in_array($this->findKey($leParent->Titre,'parent','Card'),$this->isShortKey)) {
				$NomChamp = $this->findKey($leParent->Titre);
				$Properties[$NomChamp] = $leParent->Id;
			}
		}

		$Update = (is_null($Obj["Id"])) ? 0:1;
		if (!$Flag = $this->insertObject($Properties,$Update)) return false;
				if (!$Obj["Id"]  && $this->driver=="mysqlDriver") {$Obj["Id"] = $Id = $GLOBALS["Systeme"]->Db[$this->Bdd]->lastInsertID(); $Insert=true;}
				else {$Id = $Obj["Id"]; $Insert=false;}
		//Fonctions d'heritage
/*		if (is_array($Obj['Heritages'])){
			foreach ($Obj["Heritages"] as $Herit){
				$Herit["ObjId"] = $Id;
				if ($Herit["NumHeritage"]=="") {
					//ALors il faut creer un nouvel heritage
					$this->createInheritedValue($Herit);
				}else{
					$this->updateInheritedValue($Herit["NumHeritage"],$Herit["Valeur"],'',$Herit["Lang"]);
				}
			}
		}*/
		//On fait une boucle qui va inserer les clefs etrangeres les unes apres les autres
		if (is_array($Obj['Parents']))foreach ($Obj['Parents'] as $leParent){
			if (is_array($leParent))if ($leParent["Action"]==0){
				$this->EraseAssociation($Obj["Id"],$leParent["Fkey"],$leParent["Id"]);
			}elseif(in_array($this->findKey($leParent["Fkey"],'parent','Card'),$this->isLongKey)){
				$Flag = $this->insertKey($leParent,$Obj['Id'],"p");
			}
			if (is_object($leParent))if ($leParent->Action==0){
				$this->EraseAssociation($Obj["Id"],$leParent->Titre,$leParent->Id);
			}elseif(in_array($this->findKey($leParent->Titre,'parent','Card'),$this->isLongKey)){
				$Flag =  $this->insertKey($leParent,$Obj['Id'],'p');
			}
		}
		$Properties["Id"] = $Id;
                $T = $Properties;
		return $T;
	}

	//-------------------------//
	// ERASE		   //
	//-------------------------//

	function Erase($Objet){
		//Efface completement un objet
		$Id = $Objet->Id;
		if ($Id=="") return false;
		return $this->DriverErase($Id);
	}

	function EraseAssociation($currentId,$beforeDs,$beforeId){
		//Efface une association
		return $this->EraseAssociation($currentId,$beforeDs,$beforeId);
	}


	//-------------------------//
	// SAUVEGARDE		   //
	//-------------------------//

	function saveData(){
		//Sauvegarde des donnnees dans des fichiers sql
		return $this->saveData();
	}
}
